# Trigger these rules by running `make generate PKG=./pkg/sql/parser` from the
# repository root to ensure your PATH includes vendored binaries.

SHELL = /usr/bin/env bash

TARGETS = sql.go keywords.go reserved_keywords.go helpmap_test.go help_messages.go
.PHONY: $(TARGETS)
all: $(TARGETS)

gen:
	mkdir -p gen

.INTERMEDIATE: gen/sql.go
gen/sql.go: gen/sql.y
	set -euo pipefail; \
	  ret=$$(cd gen && goyacc -p sql -o sql.go sql.y); \
	  if expr "$$ret" : ".*conflicts" >/dev/null; then \
	    echo "$$ret"; exit 1; \
	  fi

sql.go: gen/sql.go
	(echo "// Code generated by goyacc. DO NOT EDIT."; \
	 echo "// GENERATED FILE DO NOT EDIT"; \
	 cat $^) > $@

# This modifies the grammar to:
# - improve the types used by the generated parser for non-terminals
# - expand the help rules.
#
# For types:
# Determine the types that will be migrated to union types by looking
# at the accessors of sqlSymUnion. The first step in this pipeline
# prints every return type of a sqlSymUnion accessor on a separate line.
# The next step regular expression escapes these types. The third step
# joins all of the lines into a single line with a '|' character to be
# used as a regexp "or" meta-character. Finally, the last '|' character
# is stripped from the string.
# Then translate the original syntax file, with the types determined
# above being replaced with the union type in their type declarations.
.INTERMEDIATE: gen/sql.y
gen/sql.y: sql.y replace_help_rules.awk | gen
	set -euo pipefail; \
	TYPES=$$(awk '/func.*sqlSymUnion/ {print $$(NF - 1)}' sql.y | \
	        sed -e 's/[]\/$$*.^|[]/\\&/g' | \
	        tr '\n' '|' | \
	        sed -E '$$s/.$$//'); \
	sed -E "s_(type|token) <($$TYPES)>_\1 <union> /* <\2> */_" < sql.y | \
	awk -f replace_help_rules.awk > $@

reserved_keywords.go: sql.y reserved_keywords.awk
	awk -f reserved_keywords.awk < $< > $@.tmp || rm $@.tmp
	mv -f $@.tmp $@
	gofmt -s -w $@

keywords.go: sql.y all_keywords.awk
	awk -f all_keywords.awk < $< > $@.tmp || rm $@.tmp
	mv -f $@.tmp $@
	gofmt -s -w $@

# This target will print unreserved_keywords which are not actually
# used in the grammar.
unused_unreserved_keywords: sql.y unreserved_keywords.awk
	@for kw in $$(awk -f unreserved_keywords.awk < $<); do \
	  if [ $$(grep -c $${kw} $<) -le 2 ]; then \
	    echo $${kw}; \
	  fi \
	done

helpmap_test.go: gen/sql.y help_gen_test.sh
	@./help_gen_test.sh < $< >$@.tmp || rm $@.tmp
	mv -f $@.tmp $@
	gofmt -s -w $@

help_messages.go: sql.y help.awk
	awk -f help.awk < $< > $@.tmp || rm $@.tmp
	mv -f $@.tmp $@
	gofmt -s -w $@
